<template>
  <div v-loading="loading" class="preview">
    <div v-if="instanceData.instanceId">
      <div class="title">
        <div v-if="instanceData.staterUser">
          <avatar showY :name="instanceData.staterUser.name" :src="instanceData.staterUser.avatar"/>
        </div>
        <div class="title-info">
          <div class="name">
            <span style="margin-right: 15px; color:#000;">{{ instanceData.processDefName }}</span>
            <el-tag :type="status.type">{{ status.text }}</el-tag>
          </div>
          <div class="code">
            <span style="color:#6c6c6c;">编号：</span>
            <span class="id">{{ instanceData.instanceId }}</span>
          </div>
          <img v-if="status.img" :src="status.img" :style="isMobile ? 'right: -20px':''">
          <!--          <div style="font-size: 13px; color: rgb(142 141 141)" v-if="instanceData.staterUser">
                        由 {{instanceData.staterUser.name}} 在{{instanceData.startTime}}发起
                      </div>-->
        </div>
        <div class="extend-options" v-if="!isMobile">
          <el-tooltip class="item" effect="dark" content="打印" placement="top-start">
            <el-icon @click="showPrint"><Printer /></el-icon>
          </el-tooltip>
          <el-tooltip class="item" effect="dark" content="手机扫码" placement="top-start">
            <!-- <icon name="iconfont icon-iconfonterweima"></icon> -->
            <two-dimensional-code theme="filled" @click="scanQr"/>
          </el-tooltip>
        </div>
      </div>
      <div class="form">
        <form-render class="process-form" :mode="isMobile ? 'MOBILE' : 'PC'" ref="form" :forms="instanceData.formItems" v-model="instanceData.formData"/>
      </div>
      <div class="process">
        <process-progress :result="instanceData.result" :progress="instanceData.progress"/>
      </div>
    </div>
    <div class="actions" v-if="!instanceData.result">
      <div style="position: relative; width: 100%">
        <div class="comment" @click="comment">
          <!-- <icon name="el-icon-chatlineround"></icon> -->
          <el-icon><ChatLineRound /></el-icon>
          <div>评论</div>
        </div>
        <div v-if="activeTasks.length > 0 && showMore" class="action-more">
          <el-dropdown>
            <el-button type="primary" link>
              更多<el-icon><ArrowDown /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item v-if="opPerms?.transfer?.show" @click="handler('transfer')">
                  <!-- <icon name="iconfont icon-zhuanyi-16"></icon> -->
                  <el-icon><Switch /></el-icon>
                  {{opPerms?.transfer?.alisa}}
                </el-dropdown-item>
                <el-dropdown-item v-if="opPerms?.recall?.show" @click="handler('recall')">
                  <!-- <icon name="el-icon-failed"></icon> -->
                  <el-icon><Failed /></el-icon>
                  {{opPerms?.recall?.alisa}}
                </el-dropdown-item>
                <el-dropdown-item v-if="opPerms?.afterAdd?.show" @click="handler('afterAdd')">
                  <!-- <icon name="iconfont icon-zhaopinguanli"></icon> -->
                  <people-plus theme="filled" />
                  {{opPerms?.afterAdd?.alisa}}
                </el-dropdown-item>
                <el-dropdown-item
                  v-if="loginUser.id === instanceData.staterUser.id && opPerms?.cancel?.show"
                  @click="handler('cancel')">
                  <!-- <icon name="el-icon-refreshleft"></icon> -->
                  <el-icon><RefreshLeft /></el-icon>
                  {{opPerms?.cancel?.alisa}}
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
        <div class="cancel"  v-else-if="!instanceData.result && (opPerms.cancel || {}).show !== false && isRootUser">
          <el-button type="primary" link @click="handler('cancel')">
            <!-- <icon name="el-icon-refreshleft"></icon> -->
            <el-icon><RefreshLeft /></el-icon>
            {{(opPerms.cancel || {}).alisa || '撤销'}}
          </el-button>
        </div>
        <div v-if="activeTasks.length > 0" class="ok-refuse">
          <el-button size="small" type="danger" v-if="opPerms?.refuse?.show" round plain @click="handler('refuse')">{{opPerms?.refuse?.alisa}}</el-button>
          <el-button size="small" type="primary" v-if="opPerms?.agree?.show" round @click="handler('agree')">{{opPerms?.agree?.alisa}}</el-button>
        </div>
      </div>
    </div>
    <w-dialog v-model="printVisible" width="700px" title="打印预览" okText="打 印" @ok="doPrint">
      <template #title>
        <div>
          <span>打印预览</span>
          <el-radio-group style="margin: 0 30px" v-model="printCheck" @change="renderPrint" v-if="printTemplateConfig.customPrint">
            <el-radio :label="false">默认模板</el-radio>
            <el-radio :label="true">自定义模板</el-radio>
          </el-radio-group>
        </div>
      </template>
      <div v-if="printCheck" id="printDom" ref="print" v-html="printTemplateConfig.printTemplate"></div>
      <default-printer v-else ref="print" :status="status" :instance="instanceData"/>
    </w-dialog>
    <w-dialog v-model="actionVisible" :width="isMobile ? '100%' : '500px'" :title="actionDesc.title" okText="提 交" @ok="doAction">
      <process-action ref="action" @ok="handlerOk" :form-data="formData" v-if="actionVisible"
        :active-tasks="activeTasks" :instance="instanceData" :action="actionType" :action-desc="actionDesc"/>
    </w-dialog>
  </div>
</template>

<script>
import FormRender from '/@/views/setting/workflow/components/FormRender.vue'
import ProcessProgress from '/@/views/setting/workflow/common/ProcessProgress.vue'
import ProcessAction from '/@/views/setting/workflow/common/ProcessAction.vue'
import { Printer, ChatLineRound, ArrowDown, Switch, Failed, RefreshLeft } from '@element-plus/icons-vue'
import { TwoDimensionalCode, PeoplePlus } from '@icon-park/vue-next'
import moment from 'moment'
import { showFailToast } from 'vant'
import { Print, bindVar, getVal } from '/@/utils/utils'
import DefaultPrinter from '/@/views/setting/workflow/common/DefaultPrinter.vue'
import Cookies from 'js-cookie'
import { computed, onMounted, reactive, ref } from 'vue'
import { getLocalRes, isNotEmpty } from '/@/utils/utils'
import { ElMessage } from 'element-plus'

export default {
    name: 'ProcessInstancePreview',
    components: { 
        FormRender,
        Printer,
        TwoDimensionalCode,
        ChatLineRound,
        ArrowDown,
        Switch,
        Failed,
        PeoplePlus,
        RefreshLeft,
        ProcessProgress,
        ProcessAction,
        DefaultPrinter
    },
    props: {
      instanceId: {
        type: String,
        required: true,
      },
      nodeId: {
        type: String,
        required: false,
      },
    },
    emits: ['handler-after'],
    setup(props, context) {
      const { instanceId, nodeId } = toRefs(props)
      const form = ref()
      const action = ref()
      const print = ref()
      const state = reactive({
        printVisible: false,
        actionVisible: false,
        printCheck: false,
        loading: false,
        actionType: 'agree',
        instanceData: {},
        agreeVisible: false,
        printTemplateConfig: {
          customPrint: false,
          printTemplate: '',
        },
      })
      const loginUser = computed(() => {
        return Cookies.get('userId')
      })
      const isRootUser = computed(() => {
        return state.instanceData?.staterUser?.id === loginUser?.value
      })
      const isMobile = computed(() => {
        return window.screen.width < 450
      })
      const opPerms = computed(() => {
        const opPerms = state.instanceData.operationPerm || {}
        for(let key in opPerms){
          if (!opPerms[key]){
            opPerms[key] = {alisa: '', show: false}
          }
        }
        return opPerms
      })
      const showMore = computed(() => {
        return opPerms.value?.transfer?.show || opPerms.value?.recall?.show
              || opPerms.value?.afterAdd?.show || opPerms.value?.cancel?.show
      })
      const formatFormData = computed(() => {
        let val = {}
        getVal(
          state.instanceData.formData || {},
          state.instanceData.formItems || [],
          val
        )
        val.ownerDept = state.instanceData.starterDept
        val.owner = state.instanceData.staterUser.name
        val.startTime = state.instanceData.startTime
        return val
      })
      const status = computed(() => {
        let status = {}
        if (state.instanceData.status === 'RUNNING') {
          status.type = ''
          status.text = '进行中'
          status.img = null
        } else if (state.instanceData.status === 'COMPLETE') {
          if (state.instanceData.result === 'refuse-end') {
            status.type = 'danger'
            status.text = '审批驳回'
            status.img = getLocalRes('refuse.png')
          } else if (state.instanceData.result === 'cancel-end') {
            status.type = 'info'
            status.text = '审批已撤销'
            status.img = getLocalRes('recall.png')
          } else {
            status.type = 'success'
            status.text = '审批通过'
            status.img = getLocalRes('agree.png')
          }
        }
        return status
      })
      const activeTasks = computed(() => {
        let tasks = []
        ;(state.instanceData.progress || []).forEach((task) => {
          if (task.users) {
            task.users.forEach((tk) => {
              if (
                tk.user &&
                tk.user.id === loginUser.value &&
                !isNotEmpty(tk.finishTime)
              ) {
                tasks.push(tk)
              }
            })
          } else {
            if (
              task.user &&
              task.user.id === loginUser.value &&
              !isNotEmpty(task.finishTime)
            ) {
              tasks.push(task)
            }
          }
        })
        return tasks
      })
      const formData = computed(() => {
        //过滤出可编辑的表单字段
        let formFields = []
        let formData = {}
        getEnableEditForm(state.instanceData.formItems || [], formFields)
        formFields.forEach((k) => {
          formData[k] = state.instanceData.formData[k]
        })
        return formData
      })
      const actionDesc = computed(() => {
        switch (state.actionType) {
          case 'agree':
            return {tip: isRootUser.value? '备注':'审批意见', title: isRootUser.value?'提交审批':'同意审批'};
          case 'refuse':
            return { tip: '驳回意见', title: '拒绝审批' }
          case 'comment':
            return { tip: '评论内容', title: '添加评论' }
          case 'beforeAdd':
            return { tip: '加签意见', title: '前方增加审批人' }
          case 'afterAdd':
            return { tip: '加签意见', title: '后方增加审批人' }
          case 'transfer':
            return { tip: '转交意见', title: '转交给其他人审批' }
          case 'cancel':
            return { tip: '撤销原因', title: '撤销当前流程' }
          case 'recall':
            return { tip: '退回意见', title: '退回到之前节点' }
        }
      })
      //根据退回进行分段拆解
      const splitByRecall = (progress) => {
        //提取分段时间点
        let points = progress
          .filter((p) => p.result === 'recall')
          .map((p) => new Date(p.startTime).getTime())
        if (points.length > 0) {
          let blocks = [] //分段流程块组
          let pointer = 0 //定点索引
          points.push(new Date().getTime())
          points.forEach((point) => {
            let block = []
            for (let i = pointer; i < progress.length; i++) {
              let startTime = new Date(progress[i].startTime).getTime()
              if (startTime <= point) {
                block.push(progress[i])
              } else {
                pointer = i
                break
              }
            }
            //存段
            blocks.push(block)
          })
          //按段处理
          let processNodes = []
          blocks.forEach((block) => processNodes.push(...mergeTask(block)))
          return processNodes
        }
        return mergeTask(progress)
      }
       //合并活动节点，此处执行一段合并算法用来处理退回导致节点重合的问题
      const mergeTask = (progress) => {
        let merge = []
        progress.forEach((pg) => {
          let i = merge.findIndex((n) => n.nodeId === pg.nodeId && n.startTime === pg.startTime)
          if (i > -1) {
            //存在则合并到对象
            if (merge[i].users) {
              //已经合并过了
              merge[i].finishTime = pg.finishTime
              merge[i].users.push(pg)
              merge[i].result = getApprovalResult(
                merge[i],
                pg,
                pg.approvalMode
              )
              merge[i].comment = merge[i].comment.concat(pg.comment)
            } else {
              //没有就合并
              merge[i] = {
                agree: null,
                name: pg.name,
                nodeType: pg.nodeType,
                approvalMode: pg.approvalMode,
                nodeId: pg.nodeId,
                result: getApprovalResult(merge[i], pg, pg.approvalMode),
                startTime: merge[i].startTime,
                finishTime: pg.finishTime,
                comment: merge[i].comment.concat(pg.comment),
                users: [merge[i], pg],
              }
              merge[i].comment = merge[i].comment.sort(
                (a, b) => moment(a.createTime) - moment(b.createTime)
              )
            }
          } else {
            merge.push(pg)
          }
        })
        return merge
      }
      const getInstanceData = () => {
        state.loading = true
        // TO DO 接口
        return 
        getFormAndProcessProgress(instanceId.value, nodeId.value)
          .then((rsp) => {
            state.loading = false
            state.instanceData = rsp.data
            state.instanceData.progress = splitByRecall(rsp.data.progress)
          })
          .catch((err) => {
            state.loading = false
            ElMessage.error((err || '获取审批实例数据失败'))
          })
      }
      const getApprovalResult = (oldVal, newVal, mode) => {
        if (mode === 'OR') {
          return newVal.result ? newVal.result : oldVal.result
        } else if (mode === 'AND') {
          let rs = oldVal.result || newVal.result
          return rs === 'recall' ? 'recall' : rs
        } else {
          return newVal.result
        }
      }
      const comment = () => {
        state.actionType = 'comment'
        state.actionVisible = true
      }
      const handler = (action) => {
        state.actionType = action
        state.actionVisible = true
      }
      const doAction = () => {
        if (state.actionType !== 'recall') {
          form.value.validate((valid) => {
            if (valid) {
              action.value.submitAction()
            } else {
              state.actionVisible = false
              if (isMobile.value) {
                showFailToast('请完善表单')
              } else {
                ElMessage.warning('请完善表单')
              }
            }
          })
        } else {
          action.value.submitAction()
        }
      }
      const showPrint = () => {
        state.printVisible = true
      }
      const doPrint = () => {
        Print(state.printCheck ? print.value : print.value.$el)
      }
      const scanQr = () => {
        ElMessage.warning('敬请期待')
      }
      const handlerOk = () => {
        console.log('处理---handlerOk')
        state.actionVisible = false
        context.emit('handler-after')
      }
      const getEnableEditForm = (forms, fields) => {
        forms.forEach((f) => {
          if (f.name === 'SpanLayout') {
            getEnableEditForm(f.props.items, fields)
          } else if (f.perm === 'E') {
            fields.push(f.id)
          }
        })
      } 
      const getPrintConfig = () => {
        // TO DO 接口
        return
        getCustomPrintConfig(instanceId.value)
          .then((rsp) => {
            state.printTemplateConfig = rsp.data
          })
          .catch((err) => {
            ElMessage.error((err || '获取打印模板配置失败'))
          })
      }
      const renderPrint = (val) => {
        if (val) {
          nextTick(() => {
            bindVar(
              state.printTemplateConfig.printTemplate,
              formatFormData.value,
              'printDom'
            )
          })
      }
      }
      onMounted(() => {
        getInstanceData()
        getPrintConfig()
      })
      return {
        ...toRefs(state),
        loginUser,
        isRootUser,
        isMobile,
        opPerms,
        showMore,
        formatFormData,
        status,
        activeTasks,
        formData,
        actionDesc,
        splitByRecall,
        mergeTask,
        getApprovalResult,
        comment,
        handler,
        doAction,
        form,
        action,
        showPrint,
        doPrint,
        print,
        scanQr,
        handlerOk,
        renderPrint
      }
    }
}
</script>

<style lang="scss" scoped>
.preview {
  background: #eeeeee;
  position: relative;
  height: 100%;
  & > div:nth-child(1) {
    overflow-y: auto;
    height: 100%;
    //padding-bottom: 50px;
  }

  .actions {
    height: 30px;
    padding: 15px 0;
    position: absolute;
    width: 100%;
    bottom: 0;
    left: 0;
    z-index: 99;
    background: white;
    border-top: 1px solid #dcdfe6;
    box-shadow: 0 0 15px 0px #dad8d8;

    .ok-refuse {
      position: absolute;
      right: 20px;
    }

    .action-more {
      position: absolute;
      right: 180px;
      top: 5px;
    }

    .cancel {
      position: absolute;
      right: 20px;
      top: 5px;
    }

    .comment {
      position: absolute;
      left: 20px;
      top: -5px;
      cursor: pointer;
      text-align: center;
      font-size: 12px;

      :deep(.icon) {
        font-size: 20px;
      }

      &:hover {
        color: var(--el-color-primary);
      }
    }
  }
}
.process {
  background: white;
  padding: 20px 10px 50px 10px;
}
.title {
  background: white;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  position: relative;
  padding: 0 10px 10px 10px;
  & > div {
    color: #666666;
    display: inline-block;
  }

  .title-info {
    height: 50px;
    display: flex;
    padding: 0 10px;
    position: relative;
    flex-direction: column;
    justify-content: space-between;

    .name {
      font-size: 15px;
      color: #5e5e5e;
    }

    .code {
      font-size: 13px;
    }

    img {
      width: 80px;
      height: 80px;
      position: absolute;
      right: -100px;
      top: 30px;
      z-index: 9999;
    }
  }

  .extend-options {
    position: absolute;
    right: 0;

    :deep(.icon) {
      cursor: pointer;
      padding: 0 10px;

      &:hover {
        color: var(--el-color-primary);
      }
    }
  }
}
.form {
  margin: 15px 0;
  padding: 10px 10px 1px 10px;
  background: white;
}
</style>